/*	$Id: start.S,v 1.3 2004/05/17 10:39:22 wlin Exp $ */

/*
 * Copyright (c) 2001 Opsycon AB  (www.opsycon.se)
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Opsycon AB, Sweden.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#ifndef _KERNEL
#define _KERNEL
#endif

#include <asm.h>
#include <regnum.h>
#include <cpu.h>
#include <pte.h>
#include "pmon/arch/mips/mm/2H_chip_define.h"

#include "pmon/dev/ns16550.h"
#include "target/bonito.h"
#include "target/ls2h.h"

#define TTYDEBUG
#ifdef TTYDEBUG
#define	TTYDBG(x) \
	.rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop
#else
#define TTYDBG(x)
#endif
#define HAVE_TARGET_GETCHAR
#define	PRINTSTR(x) \
	.rdata;98: .asciz x; .text; la a0, 98b; bal stringserial; nop

#define CONFIG_CACHE_64K_4WAY 1 

#define tmpsize		s1
#define msize		s2
#define sdShape		s3
#define bonito		s4
#define dbg		s5
#define sdCfg		s6

/*
 * Coprocessor 0 register names
 */
#define CP0_INDEX $0
#define CP0_RANDOM $1
#define CP0_ENTRYLO0 $2
#define CP0_ENTRYLO1 $3
#define CP0_CONF $3
#define CP0_CONTEXT $4
#define CP0_PAGEMASK $5
#define CP0_WIRED $6
#define CP0_INFO $7
#define CP0_BADVADDR $8
#define CP0_COUNT $9
#define CP0_ENTRYHI $10
#define CP0_COMPARE $11
#define CP0_STATUS $12
#define CP0_CAUSE $13
#define CP0_EPC $14
#define CP0_PRID $15
#define CP0_CONFIG $16
#define CP0_LLADDR $17
#define CP0_WATCHLO $18
#define CP0_WATCHHI $19
#define CP0_XCONTEXT $20
#define CP0_FRAMEMASK $21
#define CP0_DIAGNOSTIC $22
#define CP0_PERFORMANCE $25
#define CP0_ECC $26
#define CP0_CACHEERR $27
#define CP0_TAGLO $28
#define CP0_TAGHI $29
#define CP0_ERROREPC $30

#define CP0_DEBUG  $23
#define CP0_DEPC   $24
#define CP0_DESAVE $31

#ifdef ACPI_S3_MODE

#define S3_REG_SAVE_AREA        0xffffffffa00f0000
#define GEN_RTC_1_REG        	0xffffffffbfef0050
#define PM1_CNT                 0xffffffffbfef0014
#define INTIEN0                 0xbfd00044
#define INTIEN1                 0xbfd0005c
#define INTIEN2                 0xbfd00074
#define INTIEN3                 0xbfd0008c
#define INTIEN4                 0xbfd000a4

#endif




/*
 *   Register usage:
 *
 *	s0	link versus load offset, used to relocate absolute adresses.
 *	s1	free
 *	s2	memory size.
 *	s3	sdShape.
 *	s4	Bonito base address.
 *	s5	dbg.
 *	s6	sdCfg.
 *	s7	rasave.
 *	s8	L3 Cache size.
 */
#ifdef LS2H03
#define NAND_SET_PARAM(x) \
     li     t0,x; \
     sw	    t0,0x18(t2);
#else
#define NAND_SET_PARAM(x) 
#endif


#ifdef BOOT_FROM_NAND

#define Index_Store_Tag_D			0x09
#define Index_Store_Tag_S			0x0B 
#define Index_Store_Tag_I                       0x08        


#define CONFREG_BASE 0xbfd00000
#define APB_BASE 0xbfe80000
#define NAND_BASE 0x60000
#define NAND_DMA_OFFSET 0x40
#define REMAP_REG 0xbfd80088
//#define REMAP_REG 0x1fd80088
#define REMAP_DDR 0x00e000f0 //0x80e00000 
#define REMAP_DDR_DMA 0x00e00000 //0x80e00000 

#endif

	.set	noreorder
	.globl	_start
	.globl	start
	.globl	__main
_start:
start:
	.globl	stack
stack = start - 0x4000		/* Place PMON stack below PMON start in RAM */

#ifdef BOOT_FROM_NAND
		    
reset_exception:
boot:
         bal 1f; nop
1:       bal 1f; nop
1:       bal 1f; nop
1:       bal 1f; nop
1:       bal 1f; nop
1:       bal 1f; nop
1:       bal 1f; nop
1:       bal 1f; nop
1:

    lui      a0, 0x8000
    #addu    a1,$0,t5
    #addu    a2,$0,t6
    li       a1,(1<<14)        #64k/4way
    li       a2,(1<<14)        #0x4000

cache_init_d4way_begin:
#a0=0x80000000 a1=icache_size,a2=dcache_size
#a3,v0 and v1 used as local registers
    mtc0     $0,CP0_TAGHI     #clear TAGHI
    li       t0,0x22
    mtc0     t0,CP0_ECC       #set ecc
    addu     v0,$0,a0         #v0 0x8000
    addu     v1,a0,a2         #v1 0xc000
    mtc0     $0,CP0_TAGLO     #clear TAGLO

1:  slt      a3,v0,v1
    beq      a3,$0,1f
    nop

    cache    Index_Store_Tag_D,0x0(v0)
    cache    Index_Store_Tag_D,0x1(v0)
    cache    Index_Store_Tag_D,0x2(v0)
    cache    Index_Store_Tag_D,0x3(v0)
    beq      $0,$0,1b
    addiu    v0,v0,0x20

1:
cache_init_i4way:
    addu     v0,$0,a0         #v0 0x8000
    addu     v1,a0,a1         #v1 0xc000
    mtc0     $0,CP0_TAGLO
    mtc0     $0,CP0_TAGHI
    mtc0     $0,CP0_ECC

1:  slt      a3,v0,v1
    beq      a3,$0,1f
    nop
    cache    Index_Store_Tag_I,0x0(v0)
    cache    Index_Store_Tag_I,0x1(v0)
    cache    Index_Store_Tag_I,0x2(v0)
    cache    Index_Store_Tag_I,0x3(v0)
    beq      $0,$0,1b
    addiu    v0,v0,0x20
1:
    nop

scache:
    lui     a0,0x8000
    lui     a2,0x0002      #512k/4way

scache_init_4way_begin:
#a0=0x80000000  a2=scache_size
#a3,v0 and v1 used as local registers
    mtc0    $0,CP0_TAGHI
    li      t0,0x22
    mtc0    t0,CP0_ECC
    addu    v0,$0,a0        #v0 0x8000
    addu    v1,a0,a2        #v1 0x8002
    mtc0    $0,CP0_TAGLO
1:  slt     a3,v0,v1
    beq     a3,$0,1f
    nop
    cache   Index_Store_Tag_S,0x0(v0)
    cache   Index_Store_Tag_S,0x1(v0)
    cache   Index_Store_Tag_S,0x2(v0)
    cache   Index_Store_Tag_S,0x3(v0)
    beq     $0,$0,1b
    addiu   v0,v0,0x20
1:
    nop
 
                               //cp config k0
     mfc0   t0,CP0_CONFIG
     ori    t0,t0,0x7
     xori   t0,t0,0x4
     mtc0   t0,CP0_CONFIG
  
     dli    t0,0xffffffffbfd80000
     dli    t1,0x180000f1
     sd     t1,0xa0(t0)
 
     dli    t0,0x20000            //128k
    
cache_refill:
     dli    t1,0xffffffff9f000000
     addu   t1,t1,t0
     ld     t1,0x0(t1)
     bnez   t0,cache_refill
     addiu  t0,-32

cache_lock:
     dli    t0,0xffffffffbfd80000 //lock 0x9f000000 - 0x9f00ffff
     .set mips64
     dli    t1,0x800000001f000000
     sd     t1,0x4210(t0)
     .set mips

     dli    t1,0xfffffffffffe0000
     sd     t1,0x4250(t0)

nand:
dma_nand_cfg_read:
#dma read ddr operation,copy code to s2 cache
     li     a1,0x9f000000
     li     a2,0x5f000100
     sw     a2,0x0(a1)          #dma_order_addr
     li     a2,0x5f000400       //0x1f001000
     sw     a2,0x4(a1)          #dma_mem_addr
     li     t0,APB_BASE
     li     t1,NAND_BASE
     or     a2,t0,t1
     li     t1,NAND_DMA_OFFSET
     or     a2,a2,t1
     and    a2,a2,0x1fffffff
     sw     a2,0x8(a1)#dma_dev_addr
#ifdef NAND_ECC_MODE
     li     a2,0x0007cd8
#else
     li     a2,0x0008000
#endif     
     sw     a2,0xc(a1)#dma_length
     li     a2,0x0
     sw     a2,0x10(a1)#dma_step_length
     li     a2,0x00000000
     sw     a2,0x14(a1)#step times
     li     a2,0x00000001
     sw     a2,0x18(a1)
    #state_reg [12] = 1 read ddr and write devices ,0 write ddr and read devices
     li     a1,0x5f000008 #which dma channel to be configured
     li     a2,CONFREG_BASE
     sw     a1,0x100(a2)
     nop

     li     a0,0x000
#ifdef NAND_ECC_MODE
     li     a1,0x903
     li     a2,0x21de0 //(1880*68/188)*204
#else
     li     a1,0x8103
     li     a2,0x20000
#endif     
     li     a3,0x209

nand_test_cmd_ddr:
     li     t0,APB_BASE
     li     t1,NAND_BASE
     or     t2,t1,t0

     and    t0,a1,0xfffffffe
     sw     t0,0x0(t2)
     NAND_SET_PARAM(0x8000000);
#ifdef NAND_ECC_MODE
     li     t1,0x000
#else
     li     t1,0x400
#endif
     sw     t1,0x4(t2)                             //256x4B
#ifdef NAND_ECC_MODE 
     li     t1,0x40d 
     sw     t1,0xc(t2)
#endif
     sw     a2,0x1c(t2)                            //length
     sw     a1,0x0(t2)
     nop

#  li t3,0xa0100000
1:
     lw     a1,0x0(t2)
     and    a1,a1,0x400
     beqz   a1,1b
     nop
#go to s2 cache
#ifdef NAND_ECC_MODE    
     li     t0,0x9f0012b0
     jr     t0


   .org 0xeb0 //1880*2 
#else
     li     t0,0x9f000400
     jr     t0


   .org 0x400 

#endif

#endif

	/* init processor state at first*/
/* NOTE!! Not more that 16 instructions here!!! Right now it's FULL! */
#ifdef  HANDLE_NMI
	/*nmi handler*/
     	mfc0    k1, COP_0_STATUS_REG
       	sll     k1, k1, 0xb
1:        
	bgtz    k1, 1b
        nop
#endif

#ifdef CLKIRQ_ENABLE 
	li	t0, SR_BOOT_EXC_VEC|0x8001	/* Exception to Boostrap Location */
	mtc0	t0, COP_0_STATUS_REG
	
	li v0,0x10000000
	mtc0 zero,$9
	mtc0 v0,$11
	mtc0	zero, COP_0_CAUSE_REG
#else
	mtc0	zero, COP_0_STATUS_REG //cuckoo
	mtc0	zero, COP_0_CAUSE_REG
	li	t0, SR_BOOT_EXC_VEC	/* Exception to Boostrap Location */
	mtc0	t0, COP_0_STATUS_REG //cuckoo
#endif

        bal     initregs
        nop

//	bal	uncached		/* Switch to uncached address space */
	nop

	bal	locate			/* Get current execute address */
	nop

uncached:
	or	ra, UNCACHED_MEMORY_ADDR
	j	ra
	nop
/*
 *  Reboot vector usable from outside pmon.
 */
	.align	8
ext_map_and_reboot:
	bal	CPU_TLBClear
	nop

	li	a0, 0xc0000000
	li	a1, 0x40000000
	bal	CPU_TLBInit
	nop
	la	v0, tgt_reboot
	la	v1, start
	subu	v0, v1
	lui	v1, 0xffc0
	addu	v0, v1
	jr	v0
	nop

/*
 *  Exception vectors here for rom, before we are up and running. Catch
 *  whatever comes up before we have a fully fledged exception handler.
 */
	.align	9			/* bfc00200 */
	la	a0,_start
	li	s0,0xbfc00000
	subu	s0,a0
	move	k0, ra		#save ra
	la	a0, v200_msg
	bal	stringserial
	nop
	b	exc_common

	.align	7			/* bfc00280 */
	move	k0, ra	#save ra
	la	a0, v280_msg
	bal	stringserial
	nop
	b	exc_common

/* Cache error */
	.align	8			/* bfc00300 */
	PRINTSTR("\r\nPANIC! Unexpected Cache Error exception! ")
	mfc0	a0, COP_0_CACHE_ERR
	bal	hexserial
	nop
	b	exc_common

/* General exception */
	.align	7			/* bfc00380 */
#ifdef CLKIRQ_ENABLE 
	mfc0 k1,COP_0_CAUSE_REG
	andi k1,0x807f
	xori k1,0x8000
	bnez k1,1f
	nop
	mfc0 k1,$11
	lui k0,0x1000
	addu k1,k0
	mtc0 k1,$11
	eret
1:	  
#endif
	la	a0,_start
	li	s0,0xbfc00000
	subu	s0,a0
	move	k0, ra		#save ra
	la	a0, v380_msg
	bal	stringserial
	nop
	b	exc_common
	
	.align	8			/* bfc00400 */
	move	k0, ra		#save ra
	la	a0, v400_msg
	bal	stringserial
	nop

#if 1
	b	exc_common
	nop

	/* Debug exception */
	.align  7           /* bfc00480 */
	#include "exc_ejtag.S"
#endif

	
exc_common:
	PRINTSTR("\r\nCAUSE=")
	mfc0	a0, COP_0_CAUSE_REG
	bal	hexserial
	nop
	PRINTSTR("\r\nSTATUS=")
	mfc0	a0, COP_0_STATUS_REG
	bal	hexserial
	nop
	PRINTSTR("\r\nERRORPC=")
	mfc0	a0, COP_0_ERROR_PC
	bal	hexserial
	nop
	PRINTSTR("\r\nEPC=")
	mfc0	a0, COP_0_EXC_PC
	bal	hexserial
	nop
	PRINTSTR("\r\nra=")
	move	a0, k0
	bal	hexserial
	nop
1:
    	b	1b
    	nop
	PRINTSTR("\r\nDERR0=")
	cfc0	a0, COP_0_DERR_0
	bal	hexserial
	nop
	PRINTSTR("\r\nDERR1=")
	cfc0	a0, COP_0_DERR_1
	bal	hexserial
	nop

//	b	ext_map_and_reboot
	nop

	.align 8
		nop
	.align 8
	.word read
	.word write
	.word open
	.word close
	.word nullfunction
	.word printf
	.word vsprintf
	.word nullfunction
	.word nullfunction
	.word getenv
	.word nullfunction
	.word nullfunction
	.word nullfunction
	.word nullfunction

#define SUPPORT_PWRUP_FROM_SELFREF
#ifdef  SUPPORT_PWRUP_FROM_SELFREF
#define GET_PWRUP_FROM_SREFRESH \
    move    a1, $0;
#endif

initregs:
        ## init registers
        .set    noat
        move    $1, $0
        move    $2, $0
        move    $3, $0
        move    $4, $0
        move    $5, $0
        move    $6, $0
        move    $7, $0
        move    $8, $0
        move    $9, $0
        move    $10, $0
        move    $11, $0
        move    $12, $0
        move    $13, $0
        move    $14, $0
        move    $15, $0
        move    $16, $0
        move    $17, $0
        move    $18, $0
        move    $19, $0
        move    $20, $0
        move    $21, $0
        move    $22, $0
        move    $23, $0
        move    $24, $0
        move    $25, $0
        move    $26, $0
        move    $27, $0
        move    $28, $0
        move    $29, $0
        move    $30, $0
        .set    at

	/* now begin initial float CP1 register */
        ## float point

        mfc0    t0, CP0_STATUS
        li     t1, 0x64000000|SR_KX|SR_SX|SR_UX|SR_BOOT_EXC_VEC      # {cu3,cu2,cu1,cu0}<={0110, status_fr<=1,0xe0 to enable 64bit space
        or      t0, t0, t1
        mtc0    t0, CP0_STATUS
	la       sp, stack
	la       gp, _gp
        jr       ra
        nop

/*
 *  We get here from executing a bal to get the PC value of the current execute
 *  location into ra. Check to see if we run from ROM or if this is ramloaded.
 */
locate:

	la	s0,uncached
	subu	s0,ra,s0
	bnez s0,1f
	nop
	li a0,4
	la v0,initmips
	jr v0
	nop
1:
	
	mfc0    t0, CP0_STATUS
        li     t1, 0x64000000|SR_KX|SR_SX|SR_UX|SR_BOOT_EXC_VEC      # {cu3,cu2,cu1,cu0}<={0110, status_fr<=1,0xe0 to enable 64bit space
	or      t0, t0, t1
        mtc0    t0, CP0_STATUS
        mtc0    zero,COP_0_CAUSE_REG

	//li 	t0,0xbfd00200 //enable ls2h ejtag
	//lw	t1,0x0(t0)
	//li	t2,0xfffffe70
	//and	t1,t1, t2
	//ori	t1,t1, 0x100
	//sw 	t1,0x0(t0)

	li	t0,0xbfd80090
	li	t1,0x82
	sw	t1,0x0(t0)
	li	t1,0x10000084
	sw	t1,0x8(t0)

#include "pllcfg.S"

	/* This window makes sys more stable, be carefull to remove it */
	li	a0, 0xbfd800a8
	dli	t1, 0x40000084
	sd	t1, 0x0(a0)

#define set_L2_win(mas_i, win_i, base, mask, mmap) \
	li      t0, 0xbfd80000 ;	\
	addiu   t0, t0, mas_i*0x100 ;	\
	addiu   t0, t0, win_i*0x8 ;	\
	dli     t1, base ;		\
	sd      t1, 0x0(t0) ;		\
	dli     t1, mask ;		\
	sd      t1, 0x40(t0) ;		\
	dli     t1, mmap ;		\
	sd      t1, 0x80(t0)

#define set_L1_mas6(win_i, base, mask, mmap) \
	li      t0, 0xbfd82600 ;	\
	addiu   t0, t0, win_i*0x8 ;	\
	dli     t1, base ;		\
	sd      t1, 0x0(t0) ;		\
	dli     t1, mask ;		\
	sd      t1, 0x40(t0) ;		\
	dli     t1, mmap ;		\
	sd      t1, 0x80(t0)

	#IODMA 4G 
	# 	DMA address		   CPU phy address
	# 0x00000000 ~ 0x0fffffff  ---> 0x00000000 ~ 0x010000000
	# 0x00000000 ~ 0x3fffffff  ---> 0x10000000 ~ 0x13fffffff
	# 0x40000000 ~ 0x7fffffff  ---> 0x14000000 ~ 0x17fffffff
	# 0x80000000 ~ 0xbfffffff  ---> 0x18000000 ~ 0x1bfffffff
	# 0xc0000000 ~ 0xffffffff  ---> 0x1c000000 ~ 0x1ffffffff

	# sbridge
	set_L2_win(1, 0, 0x0000000000000000, 0xfffffffff0000000, 0x00000000400000f3) # lower 256M
	set_L2_win(1, 1, 0x0000000000000000, 0xffffffffc0000000, 0x00000001400000f3) # 0~1G
	set_L2_win(1, 2, 0x0000000040000000, 0xffffffffc0000000, 0x00000002400000f3) # 1~2G
	set_L2_win(1, 3, 0x0000000080000000, 0xffffffffc0000000, 0x00000003400000f3) # 2~3G
	set_L2_win(1, 4, 0x00000000c0000000, 0xffffffffc0000000, 0x00000004400000f3) # 3~4G
	set_L2_win(1, 5, 0xffffffff80000000, 0xffffffffc0000000, 0x00000003400000f3) # 2~3G for sata/usb
	set_L2_win(1, 6, 0xffffffffc0000000, 0xffffffffc0000000, 0x00000004400000f3) # 3~4G for sata/usb

        # pcie
	set_L2_win(4, 0, 0x0000000000000000, 0xfffffffffffff000, 0x000000001fd00081) # lower 256M
#if 0
	set_L2_win(4, 1, 0x0000000000000000, 0xffffffff00000000, 0x00000000000000f0) # for uncache dma
#else
	set_L2_win(4, 1, 0x0000000000000000, 0xfffffffff0000000, 0x00000000400000f3) # lower 256M
#endif
	set_L2_win(4, 2, 0x0000000000000000, 0xffffffffc0000000, 0x00000001400000f3) # 0~1G
	set_L2_win(4, 3, 0x0000000040000000, 0xffffffffc0000000, 0x00000002400000f3) # 1~2G
	set_L2_win(4, 4, 0x0000000080000000, 0xffffffffc0000000, 0x00000003400000f3) # 2~3G
	set_L2_win(4, 5, 0x00000000c0000000, 0xffffffffc0000000, 0x00000004400000f3) # 3~4G
	set_L2_win(4, 6, 0xffffffff80000000, 0xffffffffc0000000, 0x00000003400000f3) # 2~3G for sata/usb
	set_L2_win(4, 7, 0xffffffffc0000000, 0xffffffffc0000000, 0x00000004400000f3) # 3~4G for sata/usb

        # gpu
	set_L2_win(2, 0, 0x0000000000000000, 0xfffffffff0000000, 0x00000000400000f3) # lower 256M
	set_L2_win(2, 1, 0x0000000000000000, 0xffffffffc0000000, 0x00000001400000f3) # 0~1G
	set_L2_win(2, 2, 0x0000000040000000, 0xffffffffc0000000, 0x00000002400000f3) # 1~2G
	set_L2_win(2, 3, 0x0000000080000000, 0xffffffffc0000000, 0x00000003400000f3) # 2~3G
	set_L2_win(2, 4, 0x00000000c0000000, 0xffffffffc0000000, 0x00000004400000f3) # 3~4G
	set_L2_win(2, 5, 0xffffffff80000000, 0xffffffffc0000000, 0x00000003400000f3) # 2~3G for sata/usb
	set_L2_win(2, 6, 0xffffffffc0000000, 0xffffffffc0000000, 0x00000004400000f3) # 3~4G for sata/usb

	set_L1_mas6(0, 0x0000000040000000, 0xffffffffc0000000, 0x00000000000000f0) 
	set_L1_mas6(1, 0x0000000140000000, 0xffffffffc0000000, 0x00000001000000f0) 
	set_L1_mas6(2, 0x0000000240000000, 0xffffffffc0000000, 0x00000001400000f0) 
	set_L1_mas6(3, 0x0000000340000000, 0xffffffffc0000000, 0x00000001800000f0) 
	set_L1_mas6(4, 0x0000000440000000, 0xffffffffc0000000, 0x00000001c00000f0) 
	set_L1_mas6(5, 0x0000000000000000, 0x0000000000000000, 0x00000000000000f0) # others, all to L2$ 

	//begin :Beep on -> delay -> Beep off
	bal	beep_on
	nop
#ifdef BOOT_FROM_NAND
	li	a0,0x2000000
#else
	li	a0,0x800
#endif
	1:
	addiu	a0,-1
	nop
	bnez	a0,1b
	nop
	bal	beep_off
	nop
//end

	bal	initserial
	nop
	PRINTSTR("\r\ninitserial good ^_^...\r\n")

	PRINTSTR("\r\nchip bootcfg is 0x")
    dli     t0, LS2H_BOOTCFG_ADDR
    ld      t1, 0x0(t0)
    dsrl    a0, t1, LS2H_BOOTCFG_OFFSET
    bal     hexserial
    nop

#ifdef BOOT_FROM_NAND
#ifdef NAND_ECC_MODE
	
	PRINTSTR("\r\n boot from ecc mode\r\n")
#else
	PRINTSTR("\r\n boot from nand mode\r\n")
#endif
#else
	PRINTSTR("\r\n boot from normal mode\r\n")
#endif

#ifdef SET_DDR_FREQ

#define DDRPLL_LDF_OFFSET   24
#define DDRPLL_ODF_OFFSET   22
#define DDRPLL_IDF_OFFSET   19

//Fout = Fin / idf * 2ldf / 2^odf
//set user DDRPLL configure directly, make sure the defined value NOT exceed the min and max
//#define DDRPLL_LDF  13      //8 ~ 255
//#define DDRPLL_ODF  2       //0 ~ 3
//#define DDRPLL_IDF  2       //1 ~ 7

#define DDRPLL_LDF  DDRFREQ/25
#define DDRPLL_ODF  2
#define DDRPLL_IDF  2

    bal     Is_ddr_pll_hard_ctrl_mode
    nop
    bnez    v0, 8f
    nop
    li      a0, (DDRPLL_IDF << DDRPLL_IDF_OFFSET) | (DDRPLL_ODF << DDRPLL_ODF_OFFSET) | (DDRPLL_LDF << DDRPLL_LDF_OFFSET)

	//li      a0,0x08500000 //idf = 2,ldf = 8,odf = 1 ,freq=400
    //NOT recommend use setting bellow
	//li      a0,0x0a580000 //freq = 333M
	//li      a0,0x26b80000 //freq = 266M
#if 0
    move    s1, a0
    PRINTSTR("\r\nsoft set ddr pll configue to 0x");
    move    a0, s1
    bal     hexserial
    nop
    PRINTSTR("\r\nChange soft ddr pll configure(0: skip)?: ")
    bal     inputaddress
    nop
    beqz    v0, 1f
    nop
    move    s1, v0
1:
    move    a0, s1
#endif
	bal     set_ddr_pll_freq
	nop
	PRINTSTR("\r\nsoft set ddr pll freq done\r\n");
    b       88f
    nop
8:
    PRINTSTR("\r\nddr pll is at hard control mode.");
	PRINTSTR("\r\nCurrent D4:D3 setting is 0x")
    dli     t0, LS2H_BOOTCFG_ADDR
    ld      t1, 0x0(t0)
    dsrl    a0, t1, LS2H_BOOTCFG_OFFSET
    dsrl    a0, a0, 7
    and     a0, a0, 0x3
    or      a0, a0, 0x30
	bal 	tgt_putchar
	nop
	PRINTSTR("\r\n")
    //beep some time
	bal	beep_on
	nop
	li	a0,0x4000
1:
	addiu	a0,-1
	nop
	bnez	a0,1b
	nop
	bal	beep_off
	nop
88:
#endif

	PRINTSTR("\r\n Initialize the ls2h IIC controller\r\n")
	bal     ls2h_i2c_init
	nop

start_now:

	PRINTSTR("\r\nPMON2000 MIPS Initializing. Standby...\r\n")

#if 0
	PRINTSTR("ERRORPC=")
	mfc0	a0, COP_0_ERROR_PC
	bal	hexserial
	nop

	PRINTSTR(" CONFIG=")
	mfc0	a0, COP_0_CONFIG
	bal	hexserial
	nop
	PRINTSTR("\r\n")
	
	PRINTSTR(" PRID=")
	mfc0	a0, COP_0_PRID
	bal	hexserial
	nop
	PRINTSTR("\r\n setup done\r\n");
#endif

	bnez s0,1f
	nop
	li a0,128
	la v0,initmips
	jr v0
	nop

1:

#ifndef BOOT_FROM_NAND

do_caches:
	TTYDBG("godson2 caches found\r\n")
        bal     godson2_cache_init
        nop
	TTYDBG("scache init\r\n") 
        bal	scache_init // smh
        nop

        mfc0   a0, COP_0_CONFIG     /* enable kseg0 cachability */
#if 1
        and    a0, a0, 0xfffffff8
        or     a0, a0, 0x3           // ENABLE
#else
        and    a0, a0, 0xfffffff8
        or     a0, a0, 0x2           // DISABLE
#endif
        mtc0   a0, COP_0_CONFIG

#endif	

#ifdef  BOOT_FROM_NAND

        mfc0   a0,COP_0_CONFIG     /* enable kseg0 cachability */
        and    a0,a0,0xfffffff8
        or     a0,a0,0x3           // ENABLE
        mtc0   a0, COP_0_CONFIG

#endif

/* jmp to 0x9fc... */
        lui     t0, 0xdfff ####################### go to 9fc
        ori     t0, t0, 0xffff
        bal     1f
        nop     
1:
        and     ra, ra, t0
        addiu   ra, ra, 16
        jr      ra      
        nop 
	PRINTSTR("cache enable done\r\n")

//##########################################
//DDR config start
//cxk
#include "ddr_dir/ddr_param_define.h"
#include "ddr_dir/ddr_config_define.h"
#define DISABLE_DIMM_ECC
#define PRINT_MSG
#ifndef ARB_LEVEL
//#define FIX_DDR_PARAM
#endif
#ifdef  ARB_LEVEL
#define AUTO_ARB_LEVEL
#endif
#ifdef  AUTO_ARB_LEVEL
#define CHECK_ARB_LEVEL_FREQ
#ifdef  AUTO_DDR_CONFIG
#define CHECK_ARB_LEVEL_DIMM
#endif
//#define DEBUG_AUTO_ARB_LEVEL
#endif
//#define DEBUG_DDR
//#define DEBUG_DDR_PARAM

    move    msize, $0
    move    s3, $0

//!!!!important--s1 must be correctly set

    TTYDBG("NODE 0 MEMORY CONFIG BEGIN\r\n")

#ifdef  AUTO_DDR_CONFIG
 #ifdef DIMM_ID
        dli     s1, 0xff000004+(DIMM_ID<<16)  //set use MC1 or MC0 or MC1/0 and give All device id
 #else
        dli     s1, 0xff500004  //set use MC1 or MC0 or MC1/0 and give All device id
 #endif
#else
#ifdef  DDR3_SODIMM
    //dli     s1, 0x00000000c0a10404
    dli     s1, ( MC_SDRAM_TYPE_DDR3    /* sdram type: DDR3/DDR2 */ \
                | MC_DIMM_ECC_NO        /* dimm ECC: YES/NO */ \
                | MC_DIMM_BUF_REG_NO    /* dimm buffer register: YES/NO, for RDIMM use YES, all else use NO*/ \
                | MC_DIMM_WIDTH_64      /* memory data width: 64/32 */ \
                | MC_SDRAM_ROW_15       /* sdram row address number: 15~11 */ \
                | MC_SDRAM_COL_10       /* sdram column address number: 12~9 */ \
                | MC_SDRAM_BANK_8       /* sdram bank number: 8/4 */ \
                | MC_ADDR_MIRROR_NO     /* for standard DDR3 UDIMM, use YES, else use NO */ \
                | MC_SDRAM_WIDTH_X8     /* SDRAM device data width: 8/16 */ \
                | MC_USE_CS_0           /* the CS pins the sdram connected on(split by '_', from small to big) */ \
                | MC_MEMSIZE_(4)        /* MC memory size, unit: 512MB */ \
                )
    or      s1, s1, 0x4
#elif   DDR3_SMT
    //dli     s1, 0x00000000c0a18404
    dli     s1, ( MC_SDRAM_TYPE_DDR3    /* sdram type: DDR3/DDR2 */ \
                | MC_DIMM_ECC_NO        /* dimm ECC: YES/NO */ \
                | MC_DIMM_BUF_REG_NO    /* dimm buffer register: YES/NO, for RDIMM use YES, all else use NO*/ \
                | MC_DIMM_WIDTH_64      /* memory data width: 64/32 */ \
                | MC_SDRAM_ROW_15       /* sdram row address number: 15~11 */ \
                | MC_SDRAM_COL_10       /* sdram column address number: 12~9 */ \
                | MC_SDRAM_BANK_8       /* sdram bank number: 8/4 */ \
                | MC_ADDR_MIRROR_NO     /* for standard DDR3 UDIMM, use YES, else use NO */ \
                | MC_SDRAM_WIDTH_X16    /* SDRAM device data width: 8/16 */ \
                | MC_USE_CS_0           /* the CS pins the sdram connected on(split by '_', from small to big) */ \
                | MC_MEMSIZE_(4)        /* MC memory size, unit: 512MB */ \
                )
    or      s1, s1, 0x4
#else
    //dli     s1, 0x00000000c1e40204  //dian mian 1GB
    //dli     s1, 0x00000000c1ec0404  //shuang mian 2GB
    //dli     s1, 0x00000000c9ec0204  //shuang mian 1GB(32 bit DIMM)
                    
    dli     s1, ( MC_SDRAM_TYPE_DDR3    /* sdram type: DDR3/DDR2 */ \
                | MC_DIMM_ECC_NO        /* dimm ECC: YES/NO */ \
                | MC_DIMM_BUF_REG_NO    /* dimm buffer register: YES/NO, for RDIMM use YES, all else use NO*/ \
                | MC_DIMM_WIDTH_32      /* memory data width: 64/32 */ \
                | MC_SDRAM_ROW_14       /* sdram row address number: 15~11 */ \
                | MC_SDRAM_COL_10       /* sdram column address number: 12~9 */ \
                | MC_SDRAM_BANK_8       /* sdram bank number: 8/4 */ \
                | MC_ADDR_MIRROR_YES    /* for standard DDR3 UDIMM, use YES, else use NO */ \
                | MC_SDRAM_WIDTH_X8     /* SDRAM device data width: 8/16 */ \
                | MC_USE_CS_2_3         /* the CS pins the sdram connected on(split by '_', from small to big) */ \
                | MC_MEMSIZE_(2)        /* MC memory size, unit: 512MB */ \
                )
    //set used MC
    or      s1, s1, 0x4
#ifdef DDR_S1
	dli	s1, DDR_S1
#endif
#endif
#endif

#include "ddr_dir/loongson2H_ddr_config.S"

	/*judge the node0 whether have memory*/
	move    a0, msize
	beq     a0, 0x0, beep_on
	nop

##########################################
#ifdef  DEBUG_DDR
//#define MANAUL_INPUT

#ifdef MANAUL_INPUT
    PRINTSTR("\r\nDo test?(0xf: skip): ")
    bal     inputaddress
    nop
    and     v0, v0, 0xf
    dli     a1, 0x1
    bgt     v0, a1, 3f
    nop
#endif

    dli     s1, 0x0008000080000000  //NODE 0, start from 0x80000000
#ifdef MANAUL_INPUT
    PRINTSTR("\r\ndefault s1 = 0x");
    dsrl    a0, s1, 32
    bal     hexserial
    nop
    PRINTSTR("__")
    move    a0, s1
    bal     hexserial
    nop
    PRINTSTR("\r\nChange test param s1(0: skip)?: ")
    bal     inputaddress
    nop
    beqz    v0, 1f
    nop
    move    s1, v0
1:
#endif
1:
    dli     t1, 0x0010
    bal     test_mem
    nop
    move    t1, v0
    PRINTSTR("\r\n")
    dsrl    a0, t1, 32
    bal     hexserial
    nop
    move    a0, t1
    bal     hexserial
    nop
    beqz    t1, 2f
    nop
    PRINTSTR("  Error found!!\r\n")
2:
#if 0
    b       1b
    nop
#endif

3:

#undef MANAUL_INPUT
#endif

#ifdef ACPI_S3_MODE
/*save the address of memory for acpi*/
dli     t0,S3_REG_SAVE_AREA
dli	t1,GEN_RTC_1_REG
sw	t0,0x0(t1)
dsrl	t0,t0,32
sw	t0,0x4(t1)


dli     t0,PM1_CNT
lw      t1,0x0(t0)
li      t0,0x00001400
and     t1,t1,0x00001c00
nop

li      a1,0x000080000//must delay some time,otherwise will halt on pmon sometimes randomly  notice!!!!
1:
subu    a1,a1,0x1
bnez    a1,1b
nop

bne     t1,t0,5f
nop
PRINTSTR("\r\n resume_from_s3_mode ...\r\n")
bal     resume_from_s3_mode
nop

5:
dli     t0,PM1_CNT
li      t1,0x0
sw      t1,0x0(t0)
#endif


#ifdef  AUTO_ARB_LEVEL
#include "ddr_dir/store_auto_arb_level_info.S"
#endif
#########################################
#include "machine/newtest/newdebug.S"


bootnow:

	TTYDBG("  start = 0x")
	la	a0, start
	bal	hexserial
	nop
	TTYDBG("\r\n  s0 = 0x")
	move	a0, s0
	bal	hexserial
	nop
	TTYDBG("\r\n  _edata = 0x");
	la	a0, _edata
	bal	hexserial
	nop
	TTYDBG("\r\n  _end = 0x");
	la	a0, _end
	bal	hexserial
	nop
	TTYDBG("\r\n")
#ifdef AUTO_DDR_CONFIG
        bal  spd_info_store
	nop
#endif

#ifdef BOOT_FROM_NAND

#copy code from nand to ddr

	la	a0, start 
	li	a1, 0x0
	la	a2, _edata
	subu    a2,a2,a0
#ifdef NAND_ECC_MODE	
        li      a3,1880
	divu    a3,a2,a3
	addiu   a3,a3,1
	li      t0,1880
	mul     a2,a3,t0 //1880 align 

	bal     read_nand_check_badblock_ecc
#else

	bal     read_nand_check_badblock
#endif        
	nop
        PRINTSTR("copy to ddr done.\r\n")

#copy pmon code from nand(0x400) to REMAP_ADDR
	li	a0,REMAP_DDR_DMA 
#ifdef NAND_ECC_MODE 
	li	a2, 0x1001d0 //(1880*558)
	li      a1,0x1000
        
	bal     read_nand_check_badblock_ecc
        
	li       t0,0x000040000//must delay some time,otherwise will halt on pmon sometimes randomly  notice!!!!
1:
        subu     t0,t0,0x1
        bnez     t0,1b
        nop

#else

	li	a2, 0x100000 //1MB
	li      a1,0x400
        
	bal     read_nand_check_badblock
#endif
        nop
        PRINTSTR("copy text to REMAP_DDR done.\r\n")

	li      a0,0xbfd00100 // must stop dma for nand read
	li      a1,0x10
	sw      a1,0x0(a0)

#remap ddr address 0x00e00000 (0x80e00000) to 0xbfc00000 
	li     a0, REMAP_REG
	li     a1, REMAP_DDR
	sw     a1,0x0(a0)
	PRINTSTR("remap ddr done.\r\n")

#else

	la	a0, start
	li	a1, 0xbfc00000
	la	a2, _edata

	move	t0, a0
	move	t1, a1
	move	t2, a2

	/* copy text section */
	
1:	and	    t3,t0,0x0000ffff
	bnez	t3,2f
	nop
	move	a0,t0
	bal	hexserial
	nop
	li	a0,'\r'
	bal 	tgt_putchar
	nop

2:	lw	t3, 0(t1)
	sw	t3, 0(t0)

	addu	t0, 4
	addu	t1, 4

	blt	    t0, t2, 1b
	nop
	TTYDBG("\ncopy text section done.\r\n")

#endif
	.set noreorder
	/* Clear BSS */
	la	a0, _edata
	la	a2, _end
2:	sw	zero, 0(a0)
	bne	a2, a0, 2b
	addu	a0, 4
	TTYDBG("\nClear BSS done.\r\n")

	TTYDBG("Copy PMON to execute location done.\r\n")

/* cxk */
#if 0
	TTYDBG("Debug Testing...\r\n")
	la  	a0, start
	li	    a1, 0xbfc00000
	la  	a2, _edata

	move	t0, a0
	move	t1, a1
	move	t2, a2

1:	
	lw	t4, 0(t1)
	lw	t5, 0(t0)
    
	beq	t4, t5, 2f
	nop
	TTYDBG	("\r\n")
	move	a0, t0
	bal	hexserial
	nop
	TTYDBG	(" ")
	move	a0, t4
	bal	hexserial
	nop
	TTYDBG	(" ")
	move	a0, t5
	bal	hexserial
	nop
    	/* reread the wrong byte*/
	TTYDBG  (" ")
	lw      t4, 0(t0)
	nop
	move    a0, t4
	bal     hexserial
	nop
	/* if the reread value differs the first read, print mark */
	beq     t4, t5, 2f
	nop
	TTYDBG  ("  DDD")
2:	
	addu	t0, 4
	addu	t1, 4

    blt     t0, t2, 1b
	nop
	TTYDBG	("\r\nDebug Testing done!\r\n")
#endif
/*******************/


#ifdef BOOT_FROM_NAND
#cache_unlock:
     dli    t0,0xffffffffbfd80000 //lock 0x9f000000 - 0x9f00f000
     dli    t1,0x0000000000000000
     sd     t1,0x4210(t0)  

     dli    t1,0x0000000000000000
     sd     t1,0x4250(t0)

#endif
	move	a0,msize

	la	v0, initmips
	jalr	v0  
	nop

#if __mips64
#define MTC0 dmtc0
#else 
#define MTC0 mtc0
#endif
LEAF(CPU_TLBClear)
	li	a3, 0			# First TLB index.

	li	a2, PG_SIZE_4K
	MTC0   a2, COP_0_TLB_PG_MASK   # Whatever...

1:
	MTC0   zero, COP_0_TLB_HI	# Clear entry high.
	MTC0   zero, COP_0_TLB_LO0	# Clear entry low0.
	MTC0   zero, COP_0_TLB_LO1	# Clear entry low1.

	mtc0    a3, COP_0_TLB_INDEX	# Set the index.
	addiu	a3, 1
	li	a2, 64
	nop
	nop
	tlbwi				# Write the TLB

	bne	a3, a2, 1b
	nop

	jr	ra
	nop
END(CPU_TLBClear)

/*
 *  Set up the TLB. Normally called from start.S.
 */
LEAF(CPU_TLBInit)
	li	a3, 0			# First TLB index.

	li	a2, PG_SIZE_16M
	MTC0	a2, COP_0_TLB_PG_MASK   # All pages are 16Mb.

1:
	and	a2, a0, PG_SVPN
	MTC0	a2, COP_0_TLB_HI	# Set up entry high.

	move	a2, a0
	srl	a2, a0, PG_SHIFT 
	and	a2, a2, PG_FRAME
	ori	a2, PG_IOPAGE
	MTC0	a2, COP_0_TLB_LO0	# Set up entry low0.
	addu	a2, (0x01000000 >> PG_SHIFT)
	MTC0	a2, COP_0_TLB_LO1	# Set up entry low1.

	mtc0    a3, COP_0_TLB_INDEX	# Set the index.
	addiu	a3, 1
	li	a2, 0x02000000
	subu	a1, a2
	nop
	tlbwi				# Write the TLB

	bgtz	a1, 1b
	addu	a0, a2			# Step address 32Mb.

	jr	ra
	nop
END(CPU_TLBInit)

/*
 * Simple character printing routine used before full initialization
 */

LEAF(stringserial)
	move	a2, ra
#ifdef BOOT_FROM_NAND
        
	li      ra,0x90000000
	//li      ra,0x9f000000
#ifdef NAND_ECC_MODE
        addiu   a0,a0,0x400
#endif	
        bgtu    a2,ra,3f   
	nop
        li      s0,0x0
#ifdef NAND_ECC_MODE	
	subu    a0,a0,0x400
#endif
	nop 
3:       
#endif
	addu	a1, a0, s0
	lbu	a0, 0(a1)
1:
	beqz	a0, 2f
	nop
	bal	tgt_putchar
	addiu	a1, 1
	b	1b
	lbu	a0, 0(a1)
2:
	j	a2
	nop
END(stringserial)

LEAF(outstring)
	move	a2, ra
	move	a1, a0
	lbu	a0, 0(a1)
1:
	beqz	a0, 2f
	nop
	bal	tgt_putchar
	addiu	a1, 1
	b	1b
	lbu	a0, 0(a1)

2:
	j	a2
	nop
END(outstring)

LEAF(hexserial)
	move	a2, ra
	move	a1, a0
	li	a3, 7
1:
	rol	a0, a1, 4
	move	a1, a0
	and	a0, 0xf
	la	v0, hexchar
	addu	v0, s0
	addu	v0, a0
#ifdef BOOT_FROM_NAND
#ifdef NAND_ECC_MODE
	addiu   v0, v0,0x400 
#endif
#endif
	bal	tgt_putchar
	lbu	a0, 0(v0)

	bnez	a3, 1b
	addu	a3, -1

	j	a2
	nop
END(hexserial)
#ifdef ACPI_S3_MODE
LEAF(resume_from_s3_mode)

li      t0,INTIEN0 //disable intien0
li      t1,0x0
sw      t1,0x0(t0)

li      t0,INTIEN1 //disable intien1
li      t1,0x0
sw      t1,0x0(t0)

li      t0,INTIEN2 //disable intien2
li      t1,0x0
sw      t1,0x0(t0)

li      t0,INTIEN3 //disable intien3
li      t1,0x0
sw      t1,0x0(t0)

li      t0,INTIEN4 //disable intien4
li      t1,0x0
sw      t1,0x0(t0)

dli     t0,PM1_CNT // clear s3 flags
dli     t1,0x0
sw      t1,0x0(t0)

//restore register
dli     t0,S3_REG_SAVE_AREA
ld      v0,0x8(t0)
ld      v1,0x10(t0)
ld      a0,0x18(t0)
ld      a1,0x20(t0)
ld      a2,0x28(t0)
ld      a3,0x30(t0)
ld      s0,0x78(t0)
ld      s1,0x80(t0)
ld      s2,0x88(t0)
ld      s3,0x90(t0)
ld      s4,0x98(t0)
ld      s5,0x100(t0)
ld      s6,0x108(t0)
ld      s7,0x110(t0)
ld      k0,0x128(t0)
ld      k1,0x130(t0)
ld      gp,0x138(t0)
ld      sp,0x140(t0)
ld      s8,0x148(t0)

ld      t1,0x160(t0)
dmtc0   t1,$4

lw      t1,0x168(t0)
mtc0    t1,$5

lw      t1, 0x158(t0)
mtc0    t1, $12

sync
nop

dli     t0,S3_REG_SAVE_AREA
ld      t1,0x150(t0)    //get pc
jr      t1
nop

END(resume_from_s3_mode)
#endif







#ifdef BOOT_FROM_NAND
#define DMATBL_AREA 0xa0001000
#define CACHEDMA_START 0

LEAF(read_from_nand_to_ram_dma)
/********************
input:
       a0:start_addr
       a1:nand_addr
       a2:count
*********************/
#copy code from nand to ddr

	and     t0,a2,0xfffffff0
	addiu   t0,t0,0x10
	srl	t1,t0, 2    //length/4
	
	move	t3,a1     //nand_offset

#dma read ddr operation
     li     a1,DMATBL_AREA
     li     a2,0x5f000100
     sw     a2,0x0(a1)          #dma_order_addr
     and    a0,a0,0x0fffffff
     or     a0,a0,CACHEDMA_START
     sw     a0,0x4(a1)          #dma_mem_addr
     li     a0,APB_BASE
     li     a2,NAND_BASE
     or     a2,a0,a2
     li     a0,NAND_DMA_OFFSET
     or     a2,a2,a0
     and    a2,a2,0x1fffffff
     sw     a2,0x8(a1)#dma_dev_addr
     move   a2,t1
     sw     a2,0xc(a1)#dma_length
     li     a2,0x0
     sw     a2,0x10(a1)#dma_step_length
     li     a2,0x00000000
     sw     a2,0x14(a1)#step times
     li     a2,0x00000001
     sw     a2,0x18(a1)
     li     a2,0x10
     li     a1,CONFREG_BASE
     sw     a2,0x100(a1)

    #state_reg [12] = 1 read ddr and write devices ,0 write ddr and read devices
     li     a1,((DMATBL_AREA&0x5fffffff)|0x00000008) #which dma channel to be configured
     li     a2,CONFREG_BASE
     sw     a1,0x100(a2)
     nop

#nand operation
     li     a0,0x000
     li     a1,0x8103
     move   a2,t0  //length
     li     a3,0x209

#nand_test_cmd_ddr:
     li     t0,APB_BASE
     li     t1,NAND_BASE
     or     t2,t1,t0

     and    t0,a1,0xfffffffe
     sw     t0,0x0(t2)

     NAND_SET_PARAM(0x8000000);
     and    t1,t3,0x000007ff
     sw     t1,0x4(t2)         //ADDR_C
     srl    t1,t3,11           //t3>>11
     sw     t1,0x8(t2)         //ADDR_R
     sw     a2,0x1c(t2)        //length
     sw     a1,0x0(t2)
     nop

1:

     lw     a1,0x0(t2)
     and    a1,a1,0x400
     beqz   a1,1b
     nop

     j   ra
     nop
END(read_from_nand_to_ram_dma)  


LEAF(read_nand_spare)
/********************
input:
       a0:start_addr
       a1:nand_addr(ADDR_C is spare addr)
       a2:count
*********************/
#copy code from nand to ddr

	and     t0,a2,0xfffffff0
	addiu   t0,t0,0x10
	srl	t1,t0, 2    //length/4
	
	move	t3,a1     //nand_offset

#dma read ddr operation
     li     a1,DMATBL_AREA
     li     a2,0x5f000100
     sw     a2,0x0(a1)          #dma_order_addr
     and    a0,a0,0x0fffffff
     or     a2,a0,CACHEDMA_START
     sw     a2,0x4(a1)          #dma_mem_addr
     li     a0,APB_BASE
     li     a2,NAND_BASE
     or     a2,a0,a2
     li     a0,NAND_DMA_OFFSET
     or     a2,a2,a0
     and    a2,a2,0x1fffffff
     sw     a2,0x8(a1)#dma_dev_addr
     move   a2,t1
     sw     a2,0xc(a1)#dma_length
     li     a2,0x0
     sw     a2,0x10(a1)#dma_step_length
     li     a2,0x00000000
     sw     a2,0x14(a1)#step times
     li     a2,0x00000001
     sw     a2,0x18(a1)
     li     a2,0x10
     li     a1,CONFREG_BASE
     sw     a2,0x100(a1)

    #state_reg [12] = 1 read ddr and write devices ,0 write ddr and read devices
     li     a1,((DMATBL_AREA&0x5fffffff)|0x00000008) #which dma channel to be configured
     li     a2,CONFREG_BASE
     sw     a1,0x100(a2)
     nop

#nand operation
     li     a0,0x000
     li     a1,0x8203
     move   a2,t0  //length
     li     a3,0x209

#nand_test_cmd_ddr:
     li     t0,APB_BASE
     li     t1,NAND_BASE
     or     t2,t1,t0

     and    t0,a1,0xfffffffe
     sw     t0,0x0(t2)
     NAND_SET_PARAM(0x400000);
     and    t1,t3,0x000007ff
     or     t1,t1,0x00000800   //1<<11 
     sw     t1,0x4(t2)         //ADDR_C 
     srl    t1,t3,11           //t3>>11
     sw     t1,0x8(t2)         //ADDR_R
     sw     a2,0x1c(t2)        //length
     sw     a1,0x0(t2)
     nop

1:

     lw     a1,0x0(t2)
     and    a1,a1,0x400
     beqz   a1,1b
     nop

     j   ra
     nop
END(read_nand_spare)  

#define SPARE_AREA 0x80000000
#define NAND_BLOCK_SIZE 0x20000
#define NAND_BLOCK_SIZE_ECC  0x1d600
#define NAND_PASE_SIZE 0x800
#define TEMP_RAM_AREA 0x80020000 


LEAF(read_nand_check_badblock)
/********************
input:
       a0:start_addr
       a1:nand_start_addr
       a2:count
*********************/
     move     t9,ra
     move     t4,a0
     move     t5,a1
     move     t6,a2
2:      
     and      t7,t5,0xfffe0000 //block align 
     li       a0,SPARE_AREA
     move     a1,t7
     li       a2,16
     
     bal      read_nand_spare 
     nop
     li       a0,SPARE_AREA
     sync   
     nop
     lbu      a2,0(a0)  
     li       a1,0xff 
     bne      a1,a2,1f
     nop
     
     li       t8,NAND_BLOCK_SIZE
     bgeu     t6,t8,3f
     nop      
     move     t8,t6
3:     
     addu     t7,t7,t8 //next block start addr 
     subu     a2,t7,t5
     move     a0,t4
     move     a1,t5
     subu     t6,t6,a2              //count 
     addu     t4,t4,a2              //start_addr 
     addu     t5,t5,a2              //nand_addr
      
     bal      read_from_nand_to_ram_dma  
     nop 
     beqz     t6,2f
     nop
     b        2b
     nop 

1:
    li       t8,NAND_BLOCK_SIZE
    addu     t5,t5,t8
    bal      2b 
    nop
2:
    j   t9
    nop
END(read_nand_check_badblock)  


LEAF(read_from_nand_to_ram_dma_ecc)
/********************
input:
       a0:start_addr
       a1:nand_addr
       a2:count (must be 188*n)
*********************/
#copy code from nand to ddr

        move    t0,a2
        li      t1,188
	divu    t2,t0,t1
	li      t1,204
        mul     t2,t2,t1

	srl	t1,t0, 2    //length/4
      
        move    t0,t2  	
	move	t3,a1     //nand_offset

#dma read ddr operation
     li     a1,DMATBL_AREA
     li     a2,0x5f000100
     sw     a2,0x0(a1)          #dma_order_addr
     and    a0,a0,0x0fffffff
     or     a0,a0,CACHEDMA_START
     sw     a0,0x4(a1)          #dma_mem_addr
     li     a0,APB_BASE
     li     a2,NAND_BASE
     or     a2,a0,a2
     li     a0,NAND_DMA_OFFSET
     or     a2,a2,a0
     and    a2,a2,0x1fffffff
     sw     a2,0x8(a1)#dma_dev_addr
     move   a2,t1
     sw     a2,0xc(a1)#dma_length
     li     a2,0x0
     sw     a2,0x10(a1)#dma_step_length
     li     a2,0x00000000
     sw     a2,0x14(a1)#step times
     li     a2,0x00000001
     sw     a2,0x18(a1)
     li     a2,0x10
     li     a1,CONFREG_BASE
     sw     a2,0x100(a1)

    #state_reg [12] = 1 read ddr and write devices ,0 write ddr and read devices
     li     a1,((DMATBL_AREA&0x5fffffff)|0x00000008) #which dma channel to be configured
     li     a2,CONFREG_BASE
     sw     a1,0x100(a2)
     nop

#nand operation
     li     a0,0x000
     li     a1,0x903
     move   a2,t0  //length
     li     a3,0x40b

#nand_test_cmd_ddr:
     li     t0,APB_BASE
     li     t1,NAND_BASE
     or     t2,t1,t0

     and    t0,a1,0xfffffffe
     sw     t0,0x0(t2)
     NAND_SET_PARAM(0x8000000)
     and    t1,t3,0x000007ff
     sw     t1,0x4(t2)         //ADDR_C
     srl    t1,t3,11           //t3>>11
     sw     t1,0x8(t2)         //ADDR_R
     sw     a3,0xc(t2)
     sw     a2,0x1c(t2)        //length
     sw     a1,0x0(t2)
     nop

1:

     lw     a1,0x0(t2)
     and    a1,a1,0x400
     beqz   a1,1b
     nop

     j   ra
     nop
END(read_from_nand_to_ram_dma_ecc)  


LEAF(read_nand_spare_ecc)
/********************
input:
       a0:start_addr
       a1:nand_addr(ADDR_C is spare addr)
       a2:count (must be 188*n)
*********************/
#copy code from nand to ddr

	move    t0,a2
	srl	t1,t0, 2    //length/4
	
	move	t3,a1     //nand_offset

#dma read ddr operation
     li     a1,DMATBL_AREA
     li     a2,0x5f000100
     sw     a2,0x0(a1)          #dma_order_addr
     and    a0,a0,0x0fffffff
     or     a2,a0,CACHEDMA_START
     sw     a2,0x4(a1)          #dma_mem_addr
     li     a0,APB_BASE
     li     a2,NAND_BASE
     or     a2,a0,a2
     li     a0,NAND_DMA_OFFSET
     or     a2,a2,a0
     and    a2,a2,0x1fffffff
     sw     a2,0x8(a1)#dma_dev_addr
     move   a2,t1
     sw     a2,0xc(a1)#dma_length
     li     a2,0x0
     sw     a2,0x10(a1)#dma_step_length
     li     a2,0x00000000
     sw     a2,0x14(a1)#step times
     li     a2,0x00000001
     sw     a2,0x18(a1)
     li     a2,0x10
     li     a1,CONFREG_BASE
     sw     a2,0x100(a1)

    #state_reg [12] = 1 read ddr and write devices ,0 write ddr and read devices
     li     a1,((DMATBL_AREA&0x5fffffff)|0x00000008) #which dma channel to be configured
     li     a2,CONFREG_BASE
     sw     a1,0x100(a2)
     nop

#nand operation
     li     a0,0x000
     li     a1,0x203
     move   a2,t0  //length
     li     a3,0x40c

#nand_test_cmd_ddr:
     li     t0,APB_BASE
     li     t1,NAND_BASE
     or     t2,t1,t0

     and    t0,a1,0xfffffffe
     sw     t0,0x0(t2)
     NAND_SET_PARAM(0x400000)
     and    t1,t3,0x000007ff
     or     t1,t1,0x00000800   //1<<11 
     sw     t1,0x4(t2)         //ADDR_C 
     srl    t1,t3,11           //t3>>11
     sw     t1,0x8(t2)         //ADDR_R
     sw     a3,0xc(t2)         //time
     sw     a2,0x1c(t2)        //length
     sw     a1,0x0(t2)
     nop

1:

     lw     a1,0x0(t2)
     and    a1,a1,0x400
     beqz   a1,1b
     nop

     j   ra
     nop
END(read_nand_spare_ecc)  


LEAF(read_nand_check_badblock_ecc)
/********************
input:
       a0:start_addr
       a1:nand_start_addr
       a2:count (must be 188*n )
*********************/
     move     t9,ra
     move     t4,a0
     move     t5,a1
     move     t6,a2
2:      
     and      t7,t5,0xfffe0000 //block align 
     li       a0,SPARE_AREA
     move     a1,t7
     li       a2,16
 
     li       t0,0x22355
     li       t0,11111
     li       t0,0x000020000
4:
     subu     t0,t0,0x1
     bnez     t0,4b
     nop
     bal      read_nand_spare_ecc 
     nop

     li       a0,SPARE_AREA
     sync   
     nop
     lbu      a2,0(a0)  
     li       a1,0xff 
     bne      a1,a2,1f
     nop
     
     subu      t1,t5,t7  //inblock addr
     li        t0,2048
     divu      t0,t1,t0  
     li        t2,1880
     mul       t0,t0,t2  
     
     and       t2,t1,0x7ff //in page addr
     li        t3,204
     divu      t2,t2,t3   
     li        t3,188
     mul       t2,t2,t3   //in page ecc counts   
     
     addu      t0,t0,t2   //all counts
     li        t8,NAND_BLOCK_SIZE_ECC
     subu      t8,t8,t0
     bgeu      t6,t8,3f
     nop 
     move      t8,t6
3:      
     move     a2,t8
     move     a0,t4
     move     a1,t5
     subu     t6,t6,a2              //count 
     addu     t4,t4,a2              //start_addr 
     
     and      t1,t5,0xfffe0000      //block align 
     li       t2,NAND_BLOCK_SIZE
     addu     t5,t1,t2              //nand_addr
     bal      read_from_nand_to_ram_dma_ecc  
     nop
      
     beqz     t6,2f
     nop
     b        2b
     nop 

1:
    li       t8,NAND_BLOCK_SIZE
    addu     t5,t5,t8
    bal      2b 
    nop
2:
    j   t9
    nop
END(read_nand_check_badblock_ecc)  


#if 0
LEAF(read_nand_check_badblock)
/********************
input:
       a0:start_addr
       a1:nand_start_addr
       a2:count
*********************/
     move     t9,ra
     move     s0,a0
     move     s1,a1
     move     s2,a2
2:      
     and      s3,s1,0xfffe0000 //block align 
     li       a0,SPARE_AREA
     move     a1,s3
     li       a2,16
     
     bal      read_nand_spare 
     nop
     li       a0,SPARE_AREA
     lbu      a2,0(a0)  
     li       a1,0xff 
     bne      a1,a2,1f
     nop
     
     li       s4,NAND_BLOCK_SIZE
     bgeu     s2,s4,3f
     nop      
     move     s4,s2
3:     
     addu     s3,s3,s4 //next block start addr 
     subu     a2,s3,s1
     move     a0,s0
     move     a1,s1
     subu     s2,s2,a2              //count 
     addu     s0,s0,a2              //start_addr 
     addu     s1,s1,a2              //nand_addr
      
     bal      read_from_nand_to_ram_dma  
     nop 
     beqz     s2,2f
     nop
     b        2b
     nop 

1:
    li       s4,NAND_BLOCK_SIZE
    addu     s1,s1,s4
    bal      2b 
    nop
2:
    j   t9
    nop
END(read_nand_check_badblock)  


#endif

#endif




__main:
	j	ra
	nop

	.rdata
transmit_pat_msg:
	.asciz	"\r\nInvalid transmit pattern.  Must be DDDD or DDxDDx\r\n"
v200_msg:
	.asciz	"\r\nPANIC! Unexpected TLB refill exception!\r\n"
v280_msg:
	.asciz	"\r\nPANIC! Unexpected XTLB refill exception!\r\n"
v380_msg:
	.asciz	"\r\nPANIC! Unexpected General exception!\r\n"
v400_msg:
	.asciz	"\r\nPANIC! Unexpected Interrupt exception!\r\n"
hexchar:
	.ascii	"0123456789abcdef"

	.text
	.align	2

#define Index_Store_Tag_D			0x09
#define Index_Invalidate_I			0x00
#define Index_Writeback_Inv_D			0x01
#define Index_Writeback_Inv_S			0x01//delete scache  
#define Index_Store_Tag_S			0x0B 

LEAF(nullfunction)
	jr ra
	nop
END(nullfunction)

#define CP0_ECC  $26

LEAF(scache_init)
	move	t7, ra

        lui     a0, 0x8000
        lui     a2, 0x0004      #1M/4way
scache_init_4way:
#a0=0x80000000, a2=scache_size
#a3, v0 and v1 used as local registers
        li      t0, 0x22
        mtc0    t0, CP0_ECC
        mtc0    $0, CP0_TAGHI
        mtc0    $0, CP0_TAGLO
        addu    v0, $0, a0
        addu    v1, a0, a2
1:      slt     a3, v0, v1
        beq     a3, $0, 1f
        nop
        cache   Index_Store_Tag_S, 0x0(v0)
        cache   Index_Store_Tag_S, 0x1(v0)
        cache   Index_Store_Tag_S, 0x2(v0)
        cache   Index_Store_Tag_S, 0x3(v0)
        beq     $0, $0, 1b
        addiu   v0, v0, 0x20
1:
scache_init_finish:
	TTYDBG	("\r\nscache init ok\r\n")
        jr      t7
	nop
scache_init_panic:
	TTYDBG	("\r\nscache init panic\r\n")
1:      b       1b
        nop
END(scache_init)

LEAF(tlb_init)
        mtc0    $0, CP0_WIRED
        mtc0    $0, CP0_PAGEMASK
tlb_flush_all:
        lui     a0, 0x8000
        addiu   a1, $0, 64
        #a0=KSEG0,a1 = tlbsize, v0, v1, a3 used as local registers
        mtc0    $0, CP0_ENTRYLO0
        mtc0    $0, CP0_ENTRYLO1
        mfc0    v0, CP0_WIRED
        addu    v1, $0, a0
1:      sltu    a3, v0, a1
        beq     a3, $0, 1f
        nop
        mtc0    v1, CP0_ENTRYHI
        mtc0    v0, CP0_INDEX
        tlbwi
        addiu   v1, v1, 0x2000
        beq     $0, $0, 1b
        addiu   v0, v0, 1
1:
        ###tlb_init finish####
        tlbp
END(tlb_init)
###############################
LEAF(hexserial64)
	move	t7, ra
	move	t6, a0
	dsrl	a0, 32
	bal	hexserial
	nop
	move	a0, t6
	bal	hexserial
	nop
	jr	t7
    nop
END(hexserial64)

LEAF(smh_flush_dcache)
	li	a0, 0x80000000
	li	a1, (1<<14)
        addu    v0, $0, a0
        addu    v1, a0, a1
1:      slt     a3, v0, v1
        beq     a3, $0, 1f
        nop
        cache   0x01, 0x0(v0)   // Index_Writeback_Inv_D
        cache   0x01, 0x1(v0)
        cache   0x01, 0x2(v0)
        cache   0x01, 0x3(v0)
        beq     $0, $0, 1b
        addiu   v0, v0, 0x20
	jr	ra
	nop
END(smh_flush_dcache)

LEAF(godson2_cache_init)
####part 2####
cache_detect_4way:
        mfc0    t4, CP0_CONFIG
        andi    t5, t4, 0x0e00
        srl     t5, t5, 9
        andi    t6, t4, 0x01c0
        srl     t6, t6, 6
        addiu   t6, t6, 10      #4way
        addiu   t5, t5, 10      #4way
        addiu   t4, $0, 1
        sllv    t6, t4, t6
        sllv    t5, t4, t5
        addiu   t7, $0, 4
####part 3####
        lui     a0, 0x8000
        #addu    a1, $0, t5
        #addu    a2, $0, t6
        li      a1, (1<<14) #64k/4way
        li      a2, (1<<14)
cache_init_d4way:
#a0=0x80000000, a1=icache_size, a2=dcache_size
#a3, v0 and v1 used as local registers
        mtc0    $0, CP0_TAGHI
        li      t0, 0x22
        mtc0    t0, CP0_ECC
        addu    v0, $0, a0
        addu    v1, a0, a2
1:      slt     a3, v0, v1
        beq     a3, $0, 1f
        nop
        mtc0    $0, CP0_TAGLO
        cache   Index_Store_Tag_D, 0x0(v0)
        cache   Index_Store_Tag_D, 0x1(v0)
        cache   Index_Store_Tag_D, 0x2(v0)
        cache   Index_Store_Tag_D, 0x3(v0)
        beq     $0, $0, 1b
        addiu   v0, v0, 0x20
1:
cache_flush_i4way:
        addu    v0, $0, a0
        addu    v1, a0, a1
        mtc0    $0, CP0_TAGLO
        mtc0    $0, CP0_TAGHI
        mtc0    $0, CP0_ECC
1:      slt     a3, v0, v1
        beq     a3, $0, 1f
        nop
        cache   0x08, 0x0(v0)/*Index_Store_Tag_I*/
        cache   0x08, 0x1(v0)/*Index_Store_Tag_I*/
        cache   0x08, 0x2(v0)/*Index_Store_Tag_I*/
        cache   0x08, 0x3(v0)/*Index_Store_Tag_I*/
        beq     $0, $0, 1b
        addiu   v0, v0, 0x20
1:
cache_init_finish:
	//TTYDBG	("\r\ncache init ok\r\n")

        jr      ra
        nop
cache_init_panic:
	TTYDBG	("\r\ncache init panic\r\n")
1:      b       1b
        nop
	.end	godson2_cache_init

/* baud rate definitions, matching include/termios.h */
#define B0      0
#define B50     50      
#define B75     75
#define B110    110
#define B134    134
#define B150    150
#define B200    200
#define B300    300
#define B600    600
#define B1200   1200
#define B1800   1800
#define B2400   2400
#define B4800   4800
#define B9600   9600
#define B19200  19200
#define B38400  38400
#define B57600  57600
#define B115200 115200


LEAF(initserial)
	.set noat
	move 	AT,ra

        la      v0, COM1_BASE_ADDR
	li	a0,(125000000/ 16)/CONS_BAUD
	nop
	bal	1f
	nop

	jr AT
	nop
1:
        li      v1, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_4
        sb      v1, NSREG(NS16550_FIFO)(v0)
        li      v1, CFCR_DLAB                  #DLAB
        sb      v1, NSREG(NS16550_CFCR)(v0)
        sb      a0, NSREG(NS16550_DATA)(v0)
        srl     a0, 8
        sb      a0, NSREG(NS16550_IER)(v0)     #set BRDH
        li      v1, CFCR_8BITS                 #8bit
        sb      v1, NSREG(NS16550_CFCR)(v0)
        li      v1, MCR_DTR|MCR_RTS
        sb      v1, NSREG(NS16550_MCR)(v0)
        li      v1, 0x0
        sb      v1, NSREG(NS16550_IER)(v0)

        j       ra
        nop
		.set at
END(initserial)

LEAF(tgt_putchar)
	.set noat
	move AT,ra
	la  v0, COM1_BASE_ADDR
	bal 1f
	nop
	jr AT
	nop
  
1:
	lbu v1, NSREG(NS16550_LSR)(v0)
	and v1, LSR_TXRDY
	beqz    v1, 1b
	nop
						 
	sb  a0, NSREG(NS16550_DATA)(v0)
	j   ra
	nop
		.set at
END(tgt_putchar)

LEAF(tgt_testchar)
	.set noat
	move	AT, ra
        la      v0, COM1_BASE_ADDR
	bal	1f
	nop
	jr	AT
	nop
1:
        lbu     v1, NSREG(NS16550_LSR)(v0)
        and     v0, v1, LSR_RXRDY
        jr	ra
        nop
		.set at
END(tgt_testchar)

LEAF(tgt_getchar)
	.set noat
	move AT,ra
	la	v0, COM1_BASE_ADDR
	bal 1f
	nop
	jr AT
	nop
1:
	lbu	v1, NSREG(NS16550_LSR)(v0)
	and	v1, LSR_RXRDY
	beqz	v1, 1b
	nop
	lb	v0, NSREG(NS16550_DATA)(v0)
	jr ra
	nop
		.set at
END(tgt_getchar)
#ifndef BELL_PINS
#define BELL_PINS 0x0001
#endif

LEAF(beep_on)
	/* enable gpio0 output */
	li	t1,0xbfd000c4
	lh	t0,0(t1)
	and	t0,(~BELL_PINS)&0xffff
	sh	t0,0(t1)
	/* set gpio0 high */
	li	t1,0xbfd000cc
	lh	t0,0(t1)
	or	t0,BELL_PINS
	sh	t0,0(t1)
	
	jr	ra
	nop
END(beep_on)
	
LEAF(beep_off)
	/* enable gpio0 output */
	li	t1,0xbfd000c4
	lh	t0,0(t1)
	and	t0,(~BELL_PINS)&0xffff
	sh	t0,0(t1)
	/* set gpio0 low */
	li	t1,0xbfd000cc
	lh	t0,0(t1)
	and	t0,(~BELL_PINS)&0xffff
	sh	t0,0(t1)
	
	jr	ra
	nop
END(beep_off)

LEAF(ls2h_i2c_init)
#ifdef I2C_CONTROL1
	li	v0, LS2H_I2C1_CTR_REG
	li	v1, 0x0
	sb	v1, 0x0(v0)
	li	v0, LS2H_I2C1_PRER_LO_REG	
	li	v1, 0x2c
	sb	v1, 0x0(v0)
	li	v0, LS2H_I2C1_PRER_HI_REG	
	li	v1, 0x1
	sb	v1, 0x0(v0)
	li	v0, LS2H_I2C1_CTR_REG
	li	v1, 0x80
	sb	v1, 0x0(v0)
	jr	ra
	nop
#else
	li	v0, LS2H_I2C0_CTR_REG
	li	v1, 0x0
	sb	v1, 0x0(v0)
	li	v0, LS2H_I2C0_PRER_LO_REG	
	li	v1, 0x2c
	sb	v1, 0x0(v0)
	li	v0, LS2H_I2C0_PRER_HI_REG	
	li	v1, 0x1
	sb	v1, 0x0(v0)
	li	v0, LS2H_I2C0_CTR_REG
	li	v1, 0x80
	sb	v1, 0x0(v0)
	jr	ra
	nop
#endif
END(ls2h_i2c_init)

#include "i2c.S"

LEAF(spd_info_store)
	move    t8,ra

	TTYDBG("\r\n spd_info_store begin.\r\n")

	dli    t5, 0xffffffff8fffa000;

	dli    t7, 0xa9
	dli    t6, 0xad

	move	a0, t5
	daddiu	a1, a0, 0x200
1:
	sb	zero, 0(a0)
	daddiu	a0, 1
	bltu	a0, a1, 1b
	nop

4:
	move    a0, t7
	dli     a1, 0x2
	//GET_I2C_NODE_ID_a2
	bal     i2cread
	nop
	dli     t3, 0x80
	bltu    v0, t3, 2f
	nop
	move    t3, t5
	daddiu  t3, 0x100;
	move    t4, t5
1:
	sb      zero,0(t4)
	daddiu  t4, 0x1
	bltu    t4, t3, 1b
	nop
	b       3f
	nop
2:
	move    t4, t5
	dli     t0, 0x0 //used as counter

1:
	move    a0, t7
	move    a1, t0
	//GET_I2C_NODE_ID_a2
	bal     i2cread
	nop
	sb      v0, 0(t4)
	dli     a1, 0x100
	daddiu  t4, 0x1
	daddiu  t0, 0x1
	bne     t0, a1, 1b
	nop
3:
	daddiu  t5, 0x100
	daddiu  t7, 0x2
	bltu    t7, t6, 4b
	nop

	TTYDBG("\r\n spd_info_store done.\r\n")
	jr      t8
	nop
END(spd_info_store)

#ifdef SET_DDR_FREQ
#include "ddr_dir/2H_ddr_pll_config.S"
#endif
#######################################
#ifdef  AUTO_DDR_CONFIG
#include "ddr_dir/detect_node_dimm.S"
#endif

#include "ddr_dir/2H_ddr_config.S"
#ifdef ARB_LEVEL
//#define USE_SPECIAL_WRLVL_DQ_DELAY
#ifdef  USE_SPECIAL_WRLVL_DQ_DELAY
#define WRLVL_DQ_SPECIAL_DLY 0x2424242424242424 //specific the wrlvl_dq_delay for each byte lane
#endif
#include "ddr_dir/ARB_level_new.S"
#endif
#ifdef  DEBUG_DDR
#include "ddr_dir/Test_Mem.S"
#endif

    .text
    .global ddr2_reg_data
    .global ddr3_reg_data

    .align  5
//#include "loongson3A3_ddr_param.S"
#ifdef LS2H_MODULE_03
#include "loongson3A3_ddr_param-mt.S"
#else
#include "loongson3A3_ddr_param.400.S"
#endif

#ifdef  ARB_LEVEL
    .text
    .global c0_mc0_level_info 
    .global c0_mc1_level_info 

#include "ddr_dir/loongson3A3_ddr_param.lvled.S"
#else
#ifdef FIX_DDR_PARAM
#include "loongson3A3_ddr_param.fix.S"
#endif
#endif

	.text
	.global  nvram_offs
	.align 12
nvram_offs:
	.dword 0x0
	.align 12
	.dword 0x0
